using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using QY.ThreadPool;

namespace DownloadBook{
    public class ContentServer{
        public delegate void ExtractContentCallbck(bool success, string str);

        private static readonly Regex m_RegBr = new Regex("<[/]*?[\\s]*?br[\\s]*?[/]*?>", RegexOptions.IgnoreCase);
        private static readonly Regex m_RegB = new Regex("<[/]*?b>", RegexOptions.IgnoreCase);
        private static readonly Regex m_RegCr = new Regex("\r", RegexOptions.IgnoreCase);
        private static readonly Regex m_ReglfOne = new Regex("\n", RegexOptions.IgnoreCase);
        private static readonly Regex m_ReglfThree = new Regex("\n\n\n", RegexOptions.IgnoreCase);
        private static readonly Regex m_RegP = new Regex("<[/]{0,1}p>", RegexOptions.IgnoreCase);
        private static readonly Regex m_RegSpan = new Regex("&nbsp;", RegexOptions.IgnoreCase);
        private static readonly Regex m_RegStrong = new Regex("<[/]{0,1}strong>", RegexOptions.IgnoreCase);

        
        private static readonly Regex m_RegStartSpace = new Regex("^[\n]{1,}", RegexOptions.IgnoreCase);
        private static readonly Regex m_RegEndSpace = new Regex("[\n]{1,}$", RegexOptions.IgnoreCase);



        /// <summary>
        /// 提取章节内容
        /// </summary>
        /// <param name="reg"></param>
        /// <param name="html"></param>
        /// <param name="groupId"></param>
        /// <param name="regRemove"></param>
        /// <param name="dynamicAdList"></param>
        /// <param name="callback"></param>
        public static void ExtractContent(Regex reg, string html, int groupId, Regex regRemove, List<DynamicAd> dynamicAdList, ExtractContentCallbck callback) {
            System.Threading.ThreadPool.QueueUserWorkItem ((obj)=>{
                string str;
                bool result = ContentServer.ExtractContent(reg, html, groupId, regRemove, dynamicAdList, out str);
                callback(result, str);
            });
        }
        
        /// <summary>
        /// 提取章节内容
        /// </summary>
        /// <param name="reg"></param>
        /// <param name="html"></param>
        /// <param name="groupId"></param>
        /// <param name="regRemove"></param>
        /// <param name="dynamicAdList"></param>
        /// <param name="outStr"></param>
        /// <returns></returns>
        public static bool ExtractContent(Regex reg, string html, int groupId, Regex regRemove, List<DynamicAd> dynamicAdList, out string outStr) {
            bool result = false;
            outStr = "";
            if (!string.IsNullOrEmpty(html)) {
                Match match = reg.Match(html);
                if (!match.Success) {
                    outStr = "提取失败，请重新设置提取目录的正则表达式";
                } else if (match.Groups.Count < groupId) {
                    outStr = "提取失败，分组不够，分组id不正确";
                } else {
                    outStr = match.Groups[groupId].ToString();
                    outStr = ContentServer.FormatContentText(outStr, regRemove, dynamicAdList);
                    result = true;
                }
            }
            return result;
        }

        /// <summary>
        /// 格式化章节内容
        /// </summary>
        /// <param name="str"></param>
        /// <param name="regRemove"></param>
        /// <param name="dynamicAdList"></param>
        /// <returns></returns>
        public static string FormatContentText(string str, Regex regRemove, List<DynamicAd> dynamicAdList){
            string result = str;
            if (!string.IsNullOrEmpty(str)) {
                //移除用户自定义正则
                str = RemoveUserReg(str, regRemove);
                
                //html 特殊字符转码
                str = HtmlTranscodingSpecialCharacters(str);
                
                //移除动态广告
                DynamicAdServer dynamicAdServer = new DynamicAdServer();
                str = dynamicAdServer.doRemoveDynamicAd(dynamicAdList, str);

                //移除空行
                str = RemoveEmptyLine(str);

                //移除用户自定义正则
                str = RemoveUserReg(str, regRemove);

                str = m_RegStartSpace.Replace(str, "");//移除开头空行
                str = m_RegEndSpace.Replace(str, "");//移除末尾空行

                Regex m_ReglfToCrlf = new Regex("\n", RegexOptions.IgnoreCase);
                str = m_ReglfToCrlf.Replace(str, "\r\n");//替换换行为回车换行
                result = str;
            }
            return result;
        }

        /// <summary>
        /// 移除用户自定义正则
        /// </summary>
        /// <param name="str"></param>
        /// <param name="regRemove"></param>
        /// <returns></returns>
        protected static string RemoveUserReg(string str, Regex regRemove){
            if(regRemove != null) {
                str = regRemove.Replace(str, "");//移除用户指定的内容
            }
            return str;
        }

        /// <summary>
        /// 移除空行
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        protected static string RemoveEmptyLine(string str){
            string [] lines = str.Split('\n');
            StringBuilder sb = new StringBuilder();
            for(int i = 0; i < lines.Length; i++) {
                string line = lines[i].Trim();
                if (!string.IsNullOrEmpty(line)) {
                    if(sb.Length > 0) {
                        sb.Append("\n");
                    }
                    sb.Append("    ");
                    sb.Append(line);
                }
            }
            str = sb.ToString();
            sb.Clear();
            return str;
        }
        
        /// <summary>
        /// Html 特殊字符转码
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        protected static string HtmlTranscodingSpecialCharacters(string html){
            string str = html;
            if(!string.IsNullOrEmpty(str)){
                if(str.Contains("&")){//如果包含这个字符，才有必要执行下面的代码
                    str = HttpUtility.HtmlDecode(str);
                }
                
                str = m_RegSpan.Replace(str, " ");//替换空格
                str = m_RegBr.Replace(str, "\n");//替换<br />为换行
                str = m_RegP.Replace(str, "\n");//替换<p>、</p>为换行
                str = m_RegB.Replace(str, "");//移除掉加粗 html
                str = m_RegCr.Replace(str, "");//移除\r
                str = m_RegStrong.Replace(str, "");//移除<strong>

                str = m_ReglfOne.Replace(str, "\n\n");//替换一个换行为两个
                string strTemp = str;
                for(;;) {
                    strTemp = m_ReglfThree.Replace(str, "\n\n");//替换三个换行为两个
                    if(strTemp == str) {
                        break;
                    }
                    str = strTemp;
                }
            }
            return str;
        }
    }
}